package cn.com.joycode.nimble.core.message;

import cn.com.joycode.nimble.core.error.NbError;
import cn.com.joycode.nimble.core.error.NbErrorCommon;
import cn.com.joycode.nimble.core.lang.AbstractNbObject;
import cn.com.joycode.nimble.core.utils.ObjectMapperUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * @author Max Woods
 */

@Slf4j
public class NbMsg extends AbstractNbObject {

    @Getter
    private NbMsgHeader header;

    @Getter
    private NbMsgError error;

    @Getter
    private NbMsgMsgBody body = new NbMsgMsgBody();

    @JsonIgnore
    @Getter
    private NbMsgMsgCache cache = new NbMsgMsgCache();


    public NbMsg() {
        this(null, null, null);
    }

    public NbMsg(String value) {
        try {
            NbMsg tmp = ObjectMapperUtil.parseObject(value, NbMsg.class);
            if (ObjectUtil.isNull(tmp)) {
                return;
            }
            this.header = tmp.header;
            this.error = tmp.error;
            this.body = tmp.body;
        } catch (Exception e) {
            log.error("转换错误", e);
        }
    }

    public NbMsg(NbMsgType type, String sepc, String ver) {
        header = new NbMsgHeader(type, sepc, ver);
    }

    private void createError() {
        if (ObjectUtil.isNull(error)) {
            error = new NbMsgError();
        }
    }

    public void addHead(String key, Object value) {

    }

    public void setMsgError(NbError nbError) {
        createError();
        error.setError(nbError);
    }

    public void setMsgError(NbError nbError, String msg) {
        error.setError(nbError.getCode(), msg);
    }

    public void setMsgError(String code, String msg) {
        createError();
        error.setError(code, msg);
    }

    public void setMsgSubError(NbError nbError) {
        createError();
        error.setSubError(nbError);
    }

    public void setMsgSubError(String code, String msg) {
        createError();
        error.setSubError(code, msg);
    }


    public void put(String key, Object value) {
        body.put(key, value);
    }

    @SuppressWarnings("unchecked")
    public void putBody(Object value) {
        putBody(value, true);
    }

    @SuppressWarnings("unchecked")
    public void putBody(Object value, boolean clear) {
        if (ObjectUtil.isNotEmpty(value)) {
            if (clear) {
                body.clear();
            }
            body.putAll(ObjectMapperUtil.convertValue(value, Map.class));
        }
    }

    public <T> T getBody(Class<T> clazz) {
        return ObjectMapperUtil.convertValue(getBody(), clazz);
    }

    public <T> T getBody(com.fasterxml.jackson.core.type.TypeReference<T> typeReference) {
        return ObjectMapperUtil.convertValue(getBody(), typeReference);
    }

    public <T> T getBody(TypeReference<T> typeReference) {
        return Convert.convert(typeReference, getBody());
    }

    public <T> T get(String key) {
        return body.get(key);
    }

    public <T> T get(String key, Class<T> clazz) {
        return body.get(key, clazz);
    }

    public <T> T get(String key, TypeReference<T> reference) {
        return body.get(key, reference);
    }

    public String getStr(String key) {
        return body.getStr(key);
    }

    public Boolean getBool(String key) {
        return body.getBool(key);
    }

    public Integer getInt(String key) {
        return body.getInt(key);
    }

    public Long getLong(String key) {
        return body.getLong(key);
    }

    public Float getFloat(String key) {
        return body.getFloat(key);
    }

    public BigDecimal getBigDecimal(String key) {
        return body.getBigDeciaml(key);
    }

    public Date getDate(String key) {
        return body.getDate(key);
    }

    // ===============================================================================

    @SuppressWarnings("unchecked")
    public void putCache(Object value) {
        if (ObjectUtil.isNotEmpty(value)) {
            cache.putAll(ObjectMapperUtil.convertValue(value, Map.class));
        }
    }

    public void putCache(String key, Object value) {
        cache.put(key, value);
    }

    // ===============================================================================
    public boolean success() {
        if (ObjectUtil.isNull(error)) {
            return false;
        }
        return StrUtil.equals(NbErrorCommon.SUCCESS.getCode(), error.getCode());
    }

    public boolean fail() {
        if (ObjectUtil.isNull(error)) {
            return false;
        }
        if (StrUtil.isBlank(error.getCode())) {
            return false;
        }
        return !StrUtil.equals(NbErrorCommon.SUCCESS.getCode(), error.getCode());
    }
}